
include("shared.lua")

ENT.RenderGroup = RENDERGROUP_BOTH

surface.CreateFont("coolvetica", 64, 400, false, false, "wac_big")
surface.CreateFont("TitleFont", 32, 400, false, false, "wac_small")

function ENT:Initialize()
	self.SeatsT=self.SeatsT or self:AddSeatTable()
	self:AddSounds()
	self.SmoothUp=0
	self.SmoothVal=0
	self.Emitter=ParticleEmitter(self:GetPos())
	self.IsOn=false
	self.LastThink=CurTime()
	self.LastAngles=self:GetAngles()
	self.AngVel=Angle(0,0,0)
	if self.RotorBlurModel then
		self.BlurCModel=ClientsideModel(self.RotorBlurModel,RENDERGROUP_OPAQUE)
		self.BlurCModel:SetNoDraw(true)
	end
	self.RotorTime=0
end

function ENT:Think()
	if !self:GetNWBool("locked") then
		local b=self:GetNWBool("active")
		if self.Sound.Start then
			if b!=self.IsOn then
				if b then
					self.Sound.Start:Play()
				else
					self.Sound.Start:Stop()
				end
				self.IsOn=b
			end
		end
		if !self.Sound.Engine:IsPlaying() then
			self.Sound.Engine:ChangePitch(0)
			self.Sound.Engine:Play()
		end
		if !self.Sound.Blades:IsPlaying() then
			self.Sound.Blades:ChangePitch(0)
			self.Sound.Blades:Play()
		end
		local frt=CurTime()-self.LastThink
		local e=LocalPlayer():GetViewEntity()
		if !ValidEntity(e) then e=LocalPlayer() end
		local pos=e:GetPos()
		local spos=self:GetPos()
		local doppler=(pos:Distance(spos+e:GetVelocity())-pos:Distance(spos+self:GetVelocity()))/200*self.SmoothVal
		self.SmoothUp=self.SmoothUp-(self.SmoothUp-self:GetNWFloat("up"))*frt*10
		self.SmoothVal=self.SmoothVal-(self.SmoothVal-self:GetNWFloat("uptime"))*frt*10
		local val=math.Clamp(self.SmoothVal*100-self.SmoothVal*self.SmoothUp*3+doppler, 0, 200)
		self.Sound.Engine:ChangePitch(val)
		self.Sound.Engine:ChangeVolume(math.Clamp(val/100,0,1))
		self.Sound.Blades:ChangePitch(val)
		self.Sound.Blades:ChangeVolume(math.Clamp(val/100,0,1))
		if self.Sound.Start then
			self.Sound.Start:ChangeVolume(math.Clamp(100-self.SmoothVal*150, 0, 100)/100)
			self.Sound.Start:ChangePitch(100-self.SmoothVal*50)
		end
		self.LastThink=CurTime()
	else
		self.Sound.Engine:Stop()
		self.Sound.Blades:Stop()
		if self.Sound.Start then
			self.Sound.Start:Stop()
		end
	end
end

function ENT:OnRemove()
	for _,s in pairs(self.Sound) do
		s:Stop()
	end
end

function ENT:DrawHUD(k,p)
	if !self.SeatsT or !self.SeatsT[k] then return end
	local aw=self:GetNWInt("seat_"..k.."_actwep")
	local twep=self.SeatsT[k].wep[aw]
	if twep.CamPos and p:GetViewEntity()==p then
		local sw=ScrW()
		local sh=ScrH()
		
		local w=sh/6
		local s=sh/3
		
		surface.SetDrawColor(255,255,255,150)
		
		surface.DrawLine(sw/2-s, sh/2-s, sw/2-s+w, sh/2-s)
		surface.DrawLine(sw/2-s, sh/2-s, sw/2-s, sh/2-s+w)
		
		surface.DrawLine(sw/2+s, sh/2-s, sw/2+s-w, sh/2-s)
		surface.DrawLine(sw/2+s, sh/2-s, sw/2+s, sh/2-s+w)
		
		surface.DrawLine(sw/2-s, sh/2+s, sw/2-s+w, sh/2+s)
		surface.DrawLine(sw/2-s, sh/2+s, sw/2-s, sh/2+s-w)
		
		surface.DrawLine(sw/2+s, sh/2+s, sw/2+s-w, sh/2+s)
		surface.DrawLine(sw/2+s, sh/2+s, sw/2+s, sh/2+s-w)
		
		local lasts=self:GetNWFloat("seat_"..k.."_"..aw.."_lastshot")
		local nexts=self:GetNWFloat("seat_"..k.."_"..aw.."_nextshot")
		local ammo=self:GetNWInt("seat_"..k.."_"..aw.."_ammo")
	
		local width=twep.CrosshairWidth or 30
		local height=twep.CrosshairHeight or 20
		local lw=twep.CrosshairLinew or 30
		local lh=twep.CrosshairLineh or 20
		
		if twep.DrawCrosshair then
			twep.DrawCrosshair(self,twep,LocalPlayer())
		else
			if ammo==self.SeatsT[k].wep[self:GetNWInt("seat_"..k.."_actwep")].MaxAmmo and nexts>CurTime() then
				surface.SetDrawColor(255,255,255,math.sin(CurTime()*10)*75+75)
			else
				surface.SetDrawColor(255,255,255,150)
			end
			
			surface.DrawOutlinedRect(sw/2-width,sh/2-height,width*2,height*2)
			surface.DrawOutlinedRect(sw/2-width-1,sh/2-height-1,width*2+2,height*2+2)
			
			surface.DrawLine(sw/2,sh/2-height,sw/2,sh/2-height-lh)
			surface.DrawLine(sw/2-1,sh/2-height-1,sw/2-1,sh/2-height-lh)

			surface.DrawLine(sw/2,sh/2+height,sw/2,sh/2+height+lh)
			surface.DrawLine(sw/2-1,sh/2+height+1,sw/2-1,sh/2+height+lh)
			
			surface.DrawLine(sw/2-width-1,sh/2,sw/2-width-lw-1,sh/2)
			surface.DrawLine(sw/2-width-1,sh/2-1,sw/2-width-lw-1,sh/2-1)
			
			surface.DrawLine(sw/2+width+1,sh/2,sw/2+width+lw+1,sh/2)
			surface.DrawLine(sw/2+width+1,sh/2-1,sw/2+width+lw+1,sh/2-1)
		end
		
		local count=0
		for i,wep in pairs(self.SeatsT[k].wep) do
			if type(wep)=="table" and wep.Name!="No Weapon" then
				count=count+1
				if i==self:GetNWInt("seat_"..k.."_actwep") then			--background active weapon
					surface.SetDrawColor(10,10,10,150)
					surface.DrawRect(sw/2+w*2,sh/7+count*50,w*2+10,50)
				end
			end
		end
		surface.SetDrawColor(10,10,10,100)								--background
		surface.DrawRect(sw/2+w*2,sh/7+50,w*2+10,count*50)
		surface.SetDrawColor(255,255,255,200)
		surface.DrawOutlinedRect(sw/2+w*2,sh/7+50,w*2+10,count*50)	--background outline
		surface.SetFont("wac_small")
		surface.SetTextColor(230,230,230,255)
		local h=1
		for i,wep in pairs(self.SeatsT[k].wep) do
			if type(wep)=="table" and wep.Name!="No Weapon" then		--weapon name and ammo
				local a=self:GetNWInt("seat_"..k.."_"..i.."_ammo")
				surface.SetTextPos(sw/2+w*2+5,sh/7+5+h*50)
				surface.DrawText(wep.Name)
				surface.SetTextPos(sw/2+w*4+5-string.len(a)*14,sh/7+5+h*50)
				surface.DrawText(a)
				surface.SetDrawColor(255,255,255,200)
				local lastshot=self:GetNWFloat("seat_"..k.."_"..i.."_lastshot")
				local nextshot=self:GetNWFloat("seat_"..k.."_"..i.."_nextshot")
				surface.DrawRect(sw/2+w*2,sh/7+h*50+40,(w*2+10)*math.Clamp((nextshot-CurTime())/(nextshot-lastshot),0,1),10)
				h=h+1
			end
		end
		--[[surface.SetDrawColor(255,255,255,200)
		surface.DrawRect(sw/2+w*2+5,sh/7+10+h*50,math.Clamp((nexts-CurTime())/(nexts-lasts),0,1)*70,10)
		surface.SetTextPos(sw/2+w*2+5,sh/7+20+h*50)
		--surface.SetFont("MenuLarge")
		if ammo==self.SeatsT[k].wep[self:GetNWInt("seat_"..k.."_actwep")].MaxAmmo and nexts>CurTime() then
			surface.SetTextColor(255,255,255,math.sin(CurTime()*10)*100+100)
			surface.DrawText("RELOADING")
		else
			surface.SetTextColor(255,255,255,200)
			surface.DrawText(ammo)
		end]]
	end
end

function ENT:CalcThirdPersonView(k,p,pos,ang,view)
	local a=WAC.KeyDown(tonumber(p:GetInfo("wac_cl_heli_key_15")))
	local b=p:GetInfo("wac_cl_heli_mouse")=="1"
	local c=p:GetInfo("wac_cl_heli_usejoystick")=="1"
	if k==1 then
		if a then
			p.wac_heli_freeaim=true
		elseif p.wac_heli_freeaim then
			p.wac_heli_freeaim=false
			p.wac_heli_resetview=true
		end
	end
	if (k==1 and (!c and a!=b) or (c and b)) or (k!=1 and a) then
		ang=self:GetAngles()
	end
	p.wac_heli_view_pos=nil
	ang:RotateAroundAxis(self:GetRight(),-10)
	view.angles=self:GetAngles()+p.wac_heli_v_ang
	if p:GetInfo("wac_cl_heli_smoothview")=="1" then
		p.wac_heli_v_smang=p.wac_heli_v_smang or self:GetAngles()
		p.wac_heli_v_smang=WAC.SmoothApproachAngles(p.wac_heli_v_smang,self:GetAngles(),20)
		p.wac_heli_v_ang=WAC.SmoothApproachAngles(p.wac_heli_v_ang,ang-p.wac_heli_v_smang,20)
	else
		p.wac_heli_v_ang=WAC.SmoothApproachAngles(p.wac_heli_v_ang,ang-self:GetAngles(),20)
	end
	local tr=util.QuickTrace(self:LocalToWorld(Vector(-50,0,100))+self:GetVelocity()/50,view.angles:Forward()*-self.ThirdPDist,{self.Entity,self:GetNWEntity("rotor_rear")})
	view.origin=tr.HitPos-tr.Normal*10
	return view
end

function ENT:CalcFirstPersonView(k,p,pos,ang,view)
	local novlag=false
	if k==1 then
		local a=WAC.KeyDown(tonumber(p:GetInfo("wac_cl_heli_key_15")))
		local b=p:GetInfo("wac_cl_heli_mouse")=="1"
		local c=p:GetInfo("wac_cl_heli_usejoystick")=="1"
		if a then
			p.wac_heli_freeaim=true
		elseif p.wac_heli_freeaim then
			p.wac_heli_freeaim=false
			p.wac_heli_resetview=true
			p.wac_heli_lastfree=CurTime()
		end
		if (!c and a!=b) or (c and b) then
			ang=self:GetAngles()
		else
			ang=p:GetAimVector():Angle()
			ang.r=self:GetAngles().r
		end
		view.angles=self:GetAngles()+p.wac_heli_v_ang
		local m=math.Clamp(CurTime()-p.wac_heli_v_time,0,1)
		if p:GetInfo("wac_cl_heli_smoothview")=="1" then
			p.wac_heli_v_smang=p.wac_heli_v_smang or self:GetAngles()
			p.wac_heli_v_smang=WAC.SmoothApproachAngles(p.wac_heli_v_smang,self:GetAngles(),20)
			p.wac_heli_v_ang=WAC.SmoothApproachAngles(p.wac_heli_v_ang,ang-p.wac_heli_v_smang,40*math.Clamp(CurTime()-(p.wac_heli_lastfree or 0),0,0.5)*2*m)
		else
			p.wac_heli_v_ang=WAC.SmoothApproachAngles(p.wac_heli_v_ang,ang-self:GetAngles(),40*math.Clamp(CurTime()-(p.wac_heli_lastfree or 0),0,0.5)*2*m)
		end
		view.origin=pos-self:GetVelocity()*0.001--+view.angles:Forward()*6
	else
		local actwep=self:GetNWInt("seat_"..k.."_actwep")
		local wep=self.SeatsT[k].wep[actwep]
		if wep.CamPos then
			view.origin=self:LocalToWorld(wep.CamPos)
			if wep.LockAngle then
				view.angles=self:GetAngles()
			else
				view.angles=p:GetAimVector():Angle()
				view.angles.r=ang.r
			end
		else
		local m=math.Clamp(CurTime()-p.wac_heli_v_time,0,1)
			view.angles=self:GetAngles()+p.wac_heli_v_ang
			if p:GetInfo("wac_cl_heli_smoothview")=="1" then
				p.wac_heli_v_smang=p.wac_heli_v_smang or self:GetAngles()
				p.wac_heli_v_smang=WAC.SmoothApproachAngles(p.wac_heli_v_smang,self:GetAngles(),20*m)
				p.wac_heli_v_ang=WAC.SmoothApproachAngles(p.wac_heli_v_ang,ang-p.wac_heli_v_smang,40*m)
			else
				p.wac_heli_v_ang=WAC.SmoothApproachAngles(p.wac_heli_v_ang,ang-self:GetAngles(),40*m)
			end
			view.origin=pos-self:GetVelocity()*0.001--+view.angles:Forward()*6
		end
	end
	return view
end

local view={}
local lastw=0
function ENT:CalcPlayerView(k,p,pos,ang)
	if !self.SeatsT or !self.SeatsT[k] then return end
	p.wac_heli_v_ang=p.wac_heli_v_ang or Angle(0,0,0)
	p.wac_heli_v_time=p.wac_heli_v_time or 0
	self.LastAngles=self:GetAngles()
	local st=self.SeatsT[k]
	local aw=self:GetNWInt("seat_"..k.."_actwep")
	local wt=st.wep[aw]
	if wt.CalcView then
		p.wac_heli_view_pos=nil
		view=wt.CalcView(self,wt,p,pos,ang,view)
		if lastw!=aw then
			p.wac_heli_resetview=true
			lastw=aw
		end
	elseif st.CalcView then
		p.wac_heli_view_pos=nil
		view=st.CalcView(self,wt,p,pos,ang,view)
	else
		if !p:GetNWBool("wac_thirdp") then
			view=self:CalcFirstPersonView(k,p,pos,ang,view)
			if p.wac_heli_view_pos then
				p.wac_heli_v_pos=self:WorldToLocal(p.wac_heli_view_pos)-self:WorldToLocal(view.origin)
				p.wac_heli_v_ang=p.wac_heli_view_ang-self:GetAngles()
				p.wac_heli_v_smang=self:GetAngles()
				p.wac_heli_v_time=CurTime()
				p.wac_heli_view_pos=nil
			end
			if p.wac_heli_v_pos and !wt.CamPos then
				local m=math.Clamp(CurTime()-p.wac_heli_v_time,0,1)*100
				WAC.SmoothApproachVector(p.wac_heli_v_pos,Vector(0,0,0),m)
				view.origin=view.origin+self:LocalToWorld(p.wac_heli_v_pos)-self:GetPos()
				view.angles=self:GetAngles()+p.wac_heli_v_ang
			else
				p.wac_heli_view_pos=nil
			end
		else
			view=self:CalcThirdPersonView(k,p,pos,ang,view)
			p.wac_heli_v_ang=WAC.SmoothApproachAngles(p.wac_heli_v_ang,view.angles-self:GetAngles(),40)
		end
	end
	return view
end

function ENT:MovePlayerView(k,p,md)
	if p.wac_heli_resetview then md:SetViewAngles(Angle(0,90,0)) p.wac_heli_resetview=false end
	local a=md:GetViewAngles()
	local id=self:GetNWInt("seat_"..k.."_actwep")
	if !self.SeatsT or !self.SeatsT[k] or !self.SeatsT[k].wep[id] then return end
	if (k==1 and p:GetInfo("wac_cl_heli_mouse")=="1" and p:GetInfo("wac_cl_heli_usejoystick")=="0" and !WAC.KeyDown(tonumber(p:GetInfo("wac_cl_heli_key_15")))) or self.SeatsT and self.SeatsT[k].wep[id].MouseControl then
		a.p=a.p-a.p*FrameTime()*6
		a.y=a.y-(a.y-90)*FrameTime()*6
	else
		a.p=math.Clamp(a.p,-90,90)
	end
	a.y=(a.y<-90 and -180 or (a.y<0 and 0 or a.y))
	md:SetViewAngles(a)
end

function ENT:DrawScreenSpaceEffects(k,p)
	if !self.SeatsT or !self.SeatsT[k] or p:GetViewEntity()!=p then return end
	local twep=self.SeatsT[k].wep[self:GetNWInt("seat_"..k.."_actwep")]
	if twep.RenderScreenSpace then twep.RenderScreenSpace(self,twep,p) end
end

function ENT:DrawRotor()
	if ValidEntity(self.BlurCModel) and self.SmoothVal>0.6 then
		self.RotorTime=self.RotorTime+self.SmoothVal*FrameTime()
		self.BlurCModel:SetPos(self:LocalToWorld(self.TopRotorPos))
		local ang=self:GetAngles()
		ang:RotateAroundAxis(self:GetUp(),-self.RotorTime*1000)
		self.BlurCModel:SetAngles(ang)
		self.BlurCModel:DrawModel()
	end
end

local HudMat=Material("WeltEnSTurm/helihud/arrow")
local HudCol=Color(70,199,50,150)
local Black=Color(0,0,0,200)
function ENT:DrawPilotHud()
	local pos = self:GetPos()
	local fwd = self:GetForward()
	local ri = self:GetRight()
	local ang = self:GetAngles()
	ang:RotateAroundAxis(ri, 90)
	ang:RotateAroundAxis(fwd, 90)
	
	local uptm = self.SmoothVal
	local upm = self.SmoothUp
	local spos=self.SeatsT[1].Pos
	cam.Start3D2D(self:LocalToWorld(Vector(20,3.75,37.75)+spos), ang,0.015)
	surface.SetDrawColor(HudCol)
	surface.DrawRect(235, 249, 10, 2)
	surface.DrawRect(255, 249, 10, 2)
	surface.DrawRect(249, 235, 2, 10)
	surface.DrawRect(249, 255, 2, 10)
	surface.DrawRect(-3, 0, 3, 500)
	surface.DrawRect(500, 0, 3, 500)
	surface.DrawRect(7, 0, 3, 500)
	surface.DrawRect(490, 0, 3, 500)
	
	surface.DrawRect(-6,-3,19,3)
	surface.DrawRect(-6,500,19,3)
	surface.DrawRect(487,-3,19,3)
	surface.DrawRect(487,500,19,3)
	surface.DrawRect(9,248,5,3)
	surface.DrawRect(485,248,5,3)
	
	surface.DrawRect(1, 500-uptm*500, 5, uptm*500)
	surface.DrawLine(30, 5*ang.r-200+2.77*ang.p, 220, 5*ang.r-200+2.77*(ang.p*0.12))
	surface.DrawLine(30, 5*ang.r-200+2.77*ang.p+1, 220, 5*ang.r-200+2.77*(ang.p*0.12)+1)
	surface.DrawLine(280, 5*ang.r-200-2.77*(ang.p*0.12), 470, 5*ang.r-200-2.77*ang.p)
	surface.DrawLine(280, 5*ang.r-200-2.77*(ang.p*0.12)+1, 470, 5*ang.r-200-2.77*ang.p+1)
	surface.SetMaterial(HudMat)
	surface.DrawTexturedRect(-20,250-upm*250-10,20,20)
	surface.DrawTexturedRectRotated(498,math.Clamp(250-self:GetVelocity().z/5.249*2,0,500),20,20,180)
	surface.SetTextColor(HudCol)
	surface.SetFont("MenuLarge")
	surface.SetTextPos(-10, 505) 
	surface.DrawText("SPD")
	surface.SetTextPos(-10, 520)
	surface.DrawText(math.floor(self:GetVelocity():Length()*0.1)) --knots (real would be 0.037, but fuck it)
	
	if self:GetNWBool("hover") then
		surface.SetTextColor(HudCol)
		surface.SetFont("MenuLarge")
		surface.SetTextPos(483, -18)
		surface.DrawText("HVR")
	end
	
	local tr=util.QuickTrace(pos,Vector(0,0,-999999),self.Entity)
	surface.SetTextPos(485,505)
	surface.DrawText("ALT")
	surface.SetTextPos(485,520)
	surface.DrawText(math.floor((pos.z-tr.HitPos.z)/16))

	cam.End3D2D()
end

function ENT:DrawWeaponSelection()
	local fwd = self:GetForward()
	local ri = self:GetRight()
	local ang = self:GetAngles()
	ang:RotateAroundAxis(ri, 90)
	ang:RotateAroundAxis(fwd, 90)
	for k,t in pairs(self.SeatsT) do
		if type(t)=="table" and !t.NoHud then
			cam.Start3D2D(self:LocalToWorld(Vector(20,5,25)+t.Pos), ang, 0.02)
			surface.DrawRect(-10, 0, 500, 30)
			surface.DrawRect(-10, 30, 10, 20)
			if t.wep then
				local actwep=self:GetNWInt("seat_"..k.."_actwep")
				if t.wep[actwep] then
					local lastshot=self:GetNWFloat("seat_"..k.."_"..actwep.."_lastshot")
					local nextshot=self:GetNWFloat("seat_"..k.."_"..actwep.."_nextshot")
					local ammo=self:GetNWInt("seat_"..k.."_"..actwep.."_ammo")
					surface.DrawRect(10, 40, math.Clamp((nextshot-CurTime())/(nextshot-lastshot), 0, 1)*480, 10)
					draw.SimpleText(k.." "..t.wep[actwep].Name, "wac_small", 0, -2.5, Black, 0)
					draw.SimpleText(nextshot>CurTime() and ammo==t.wep[actwep].MaxAmmo and "RELOADING" or ammo, "wac_small", 480, -2.5, Black, 2)
				end
			else
				draw.SimpleText(k, "wac_small", 0, -2.5, Black, 0)
			end
			cam.End3D2D()
		end
	end
end

function ENT:Draw()
    self:DrawModel()
    self:DrawRotor()
    if !self.SeatsT or self:GetNWBool("locked") then return end
    self:DrawPilotHud()
    self:DrawWeaponSelection()
    if self.SmoothVal>0.2 then
        local particle = self.Emitter:Add("sprites/heatwave",self:LocalToWorld(self.SmokePos))
        particle:SetVelocity(self:GetVelocity()+self:GetForward()*-100)
        particle:SetDieTime(0.1)
        particle:SetStartAlpha(255)
        particle:SetEndAlpha(255)
        particle:SetStartSize(20)
        particle:SetEndSize(10)
        particle:SetColor(255,255,255)
        particle:SetRoll(math.Rand(-50,50))
        self.Emitter:Finish()
    end
end
